package com.zhihuishu.micro.course.openapi.course.impl;

import com.zhihuishu.micro.course.dto.CourseDataDto;
import com.zhihuishu.micro.course.openapi.course.CCFolderOpenService;
import com.zhihuishu.micro.course.openapi.course.dto.CourseFolderDto;
import com.zhihuishu.micro.course.openapi.course.dto.CourseFolderTreeDto;
import com.zhihuishu.micro.course.service.CCDataTreenityService;
import com.zhihuishu.micro.course.service.CCFolderTreenityDBService;
import com.zhihuishu.micro.course.service.CCFolderTreenityRedisService;
import com.zhihuishu.micro.course.service.CCFolderTreenityService;
import com.zhihuishu.remote.ErrorCode;
import com.zhihuishu.remote.RemoteException;
import com.zhihuishu.remote.RemoteResult;
import com.zhihuishu.toolkit.helper.BeanHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author Jiangli
 * @date 2016/10/17 15:27
 */
@Service("courseFolderOpenService")
public class CCFolderOpenServiceImpl extends BaseOpenImpl implements CCFolderOpenService {
    @Resource
    private CCFolderTreenityService ccFolderTreenityService;
    @Resource
    private CCFolderTreenityDBService ccFolderTreenityServiceDB;
    @Resource
    private CCFolderTreenityRedisService ccFolderTreenityServiceRedis;
    @Resource
    private CCDataTreenityService ccDataTreenityService;

    private static final String moduleNameCN = "cc文件夹";


    @Override
    public RemoteResult<Void> updateByDto(CourseFolderDto chapter, long updateUserId) throws RemoteException {
        RemoteResult<Void> result=new RemoteResult<Void>();
        if(chapter==null){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ARGUMENTS_ILLEGALITY);
            return result;
        }
        try {
            com.zhihuishu.micro.course.dto.CourseFolderDto chapterDto = BeanHelper.transTo(chapter, com.zhihuishu.micro.course.dto.CourseFolderDto.class);
            ccFolderTreenityService.update(chapterDto,updateUserId);

            result.setSuccess(true);
        } catch (Exception e) {
            throw new RemoteException(e).setMessage("修改-" + moduleNameCN + "-出错!") ;
        }
        return result;
    }

    @Override
    public RemoteResult<CourseFolderDto> updateAndGetByDto(CourseFolderDto chapter, long updateUserId) throws RemoteException {
        RemoteResult<CourseFolderDto> result=new RemoteResult<CourseFolderDto>();
        if(chapter==null){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ARGUMENTS_ILLEGALITY);
            return result;
        }
        try {
            com.zhihuishu.micro.course.dto.CourseFolderDto chapterDto = BeanHelper.transTo(chapter, com.zhihuishu.micro.course.dto.CourseFolderDto.class);

            com.zhihuishu.micro.course.dto.CourseFolderDto andGet = ccFolderTreenityService.updateAndGet(chapterDto, updateUserId);

            result.setSuccess(true);
            result.setResult(BeanHelper.transTo(andGet, CourseFolderDto.class));

        } catch (Exception e) {
            throw new RemoteException(e).setMessage("修改-" + moduleNameCN + "-出错!") ;
        }
        return result;
    }

    @Override
    public RemoteResult<List<CourseFolderDto>> updateByDtoList(List<CourseFolderDto> dtoList, long updateUserId) throws RemoteException {
        RemoteResult<List<CourseFolderDto>> result=new RemoteResult<List<CourseFolderDto>>();
        if(dtoList==null){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ARGUMENTS_ILLEGALITY);
            return result;
        }
        try {
            //只更新所处文件夹 必须先更新父文件夹id
            doUpdateMultiFolder(dtoList, updateUserId);

            List<CourseFolderDto> ret = new ArrayList<CourseFolderDto>(dtoList.size());

            //需要在目标文件夹中判断是否重名
            for (CourseFolderDto one : dtoList) {
                com.zhihuishu.micro.course.dto.CourseFolderDto newOne = ccFolderTreenityService.refreshUniqueName(BeanHelper.transTo(one, com.zhihuishu.micro.course.dto.CourseFolderDto.class), updateUserId);
                ret.add(BeanHelper.transTo(newOne, CourseFolderDto.class));
            }

            result.setResult(ret);
            result.setSuccess(true);
        } catch (Exception e) {
            throw new RemoteException(e).setMessage("修改-" + moduleNameCN + "-出错!") ;
        }
        return result;
    }

    private void doUpdateMultiFolder(List<CourseFolderDto> dtoList, long updateUserId) {
        List<com.zhihuishu.micro.course.dto.CourseFolderDto> list = new ArrayList<com.zhihuishu.micro.course.dto.CourseFolderDto>(dtoList.size());
        for (CourseFolderDto ccDataDto : dtoList) {
            list.add(BeanHelper.transTo(ccDataDto, com.zhihuishu.micro.course.dto.CourseFolderDto.class));
        }

        ccFolderTreenityService.updateMulti(list, updateUserId);
    }

    @Override
    public RemoteResult<Void> updatePrivilageForAllChildren(List<Integer> folderIdList, List<Integer> fileIdList, Integer newPrivilage, long updateUserId) throws RemoteException {
        RemoteResult<Void> result=new RemoteResult<Void>();
        if(folderIdList==null){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ARGUMENTS_ILLEGALITY);
            return result;
        }
        try {
            List<Integer> allFolderIds = ccFolderTreenityService.findAllChildren(folderIdList);
            allFolderIds.addAll(folderIdList);

            List<Integer> allFileIds = ccDataTreenityService.listDtoIdsByMultiOneToManyKey(convertIntToLong(allFolderIds));
            if(fileIdList != null && fileIdList.size()>0){
                allFileIds.addAll(fileIdList);
            }


            //update folder
            List<com.zhihuishu.micro.course.dto.CourseFolderDto> uFolderList = new ArrayList<com.zhihuishu.micro.course.dto.CourseFolderDto>(allFolderIds.size());
            for (Integer allFolderId : allFolderIds) {
                com.zhihuishu.micro.course.dto.CourseFolderDto one = new com.zhihuishu.micro.course.dto.CourseFolderDto();
                one.setId(allFolderId);
                one.setPrivilege(newPrivilage);
                uFolderList.add(one);
            }
            ccFolderTreenityService.updateMulti(uFolderList, updateUserId);

            //update files
            List<CourseDataDto> uFileList = new ArrayList<CourseDataDto>();
            for (Integer allFileId : allFileIds) {
                CourseDataDto one = new CourseDataDto();
                one.setId(allFileId);
                one.setPrivilege(newPrivilage);
                uFileList.add(one);
            }
            ccDataTreenityService.updateMulti(uFileList,updateUserId);

            result.setSuccess(true);
        } catch (Exception e) {
            throw new RemoteException(e).setMessage("修改权限-" + moduleNameCN + "-出错!") ;
        }
        return result;
    }

    @Override
    public RemoteResult<Void> deleteById(Integer chapterId, long deleteUserId) throws RemoteException {
        RemoteResult<Void>  result = new RemoteResult<Void>();
        if(chapterId == null){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ARGUMENTS_ILLEGALITY);
            return result ;
        }
        try {
            ccFolderTreenityService.delete(chapterId,deleteUserId);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new RemoteException(e).setMessage("删除-" + moduleNameCN + "-出错!") ;
        }
        return result;
    }

    @Override
    public RemoteResult<Void> deleteByIds(List<Integer> folderIds, long deleteUserId) throws RemoteException {
        RemoteResult<Void>  result = new RemoteResult<Void>();
        if(folderIds == null){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ARGUMENTS_ILLEGALITY);
            return result ;
        }
        try {
            //方案1
//            ccFolderTreenityService.deleteMulti(folderIds,deleteUserId);
//
//            List<Long> lFolderIdList = new ArrayList<Long>(folderIds.size());
//            for (Integer folderId : folderIds) {
//                lFolderIdList.add(Long.valueOf(folderId.intValue()));
//            }
//
//            //不会删除子文件夹
//            ccDataTreenityService.deleteMultiByMultiOneToManyKey(lFolderIdList,deleteUserId);


            //方案2
            List<Integer> allFolderIds = ccFolderTreenityService.findAllChildren(folderIds);
            allFolderIds.addAll(folderIds);

            ccFolderTreenityService.deleteMulti(allFolderIds,deleteUserId);

            List<Integer> fileIdList = ccDataTreenityService.listDtoIdsByMultiOneToManyKey(convertIntToLong(allFolderIds));

            ccDataTreenityService.deleteMulti(fileIdList,deleteUserId);

        } catch (Exception e) {
            log.error(e.getMessage());
            throw new RemoteException(e).setMessage("删除-" + moduleNameCN + "-出错!") ;
        }
        return result;
    }

    @Override
    public RemoteResult<CourseFolderDto> createByDto(CourseFolderDto courseChapterDto, long createUserId) throws RemoteException {
        RemoteResult<CourseFolderDto> result = new RemoteResult<CourseFolderDto>();
        try {
            com.zhihuishu.micro.course.dto.CourseFolderDto dbDto = BeanHelper.transTo(courseChapterDto, com.zhihuishu.micro.course.dto.CourseFolderDto.class);

            Integer newId = ccFolderTreenityService.create(dbDto, createUserId);
            dbDto.setId(newId);

            CourseFolderDto resultDto = BeanHelper.transTo(dbDto, CourseFolderDto.class);

            result.setSuccess(true);
            result.setResult(resultDto);
        } catch (Exception e) {
            log.error("保存-" + moduleNameCN + "-报错");
            throw new RemoteException(e).setMessage("保存-" + moduleNameCN + "-报错!");
        }

        return result;
    }


    @Override
    public RemoteResult<CourseFolderTreeDto> queryCourseFolderTree(long courseId) throws RemoteException {
        RemoteResult<CourseFolderTreeDto> result=new RemoteResult<CourseFolderTreeDto>();

        try {
            //库&缓存 同时查
            List<com.zhihuishu.micro.course.dto.CourseFolderDto> orgDtoList = ccFolderTreenityService.list(courseId);

            CourseFolderTreeDto rs = combineRs(orgDtoList);

            //直接查库
            if (rs.getRootDirId() == null) {
                log.warn("courseId:{} 没有rootId 直接查库",courseId);

                orgDtoList = ccFolderTreenityServiceDB.list(courseId);
                rs = combineRs(orgDtoList);
                log.warn("courseId:{} 直接查库的 rootId:{}",courseId,rs.getRootDirId());
            }

            result.setResult(rs);
        } catch (Exception e) {
            result.setSuccess(false);
            throw new RemoteException(e).setMessage("查询-" + moduleNameCN + "列表-出错!") ;
        }
        return result;
    }

    private CourseFolderTreeDto combineRs(List<com.zhihuishu.micro.course.dto.CourseFolderDto> orgDtoList) {
        CourseFolderTreeDto cftd = new CourseFolderTreeDto();
        Set<Integer> childrenDirIds = new HashSet<Integer>();
        cftd.setChildrenDirIds(childrenDirIds);

        Map<Integer, CourseFolderDto> dirs = new HashMap<Integer, CourseFolderDto>();
        cftd.setDirs(dirs);

        Map<Integer, Set<Integer>> dirMapping = new HashMap<Integer, Set<Integer>>();//set保持顺序
        cftd.setDirMapping(dirMapping);

        if (!CollectionUtils.isEmpty(orgDtoList)){
            for(com.zhihuishu.micro.course.dto.CourseFolderDto course : orgDtoList){
                CourseFolderDto one = BeanHelper.transTo(course, CourseFolderDto.class);
                Integer id = one.getId();
                Integer parentId = one.getParentId()==null?null:one.getParentId().intValue();

                if (parentId == null) {
                    cftd.setRootDirId(id);
                } else {
                    childrenDirIds.add(id);
                }

                dirs.put(id,one);


                if (parentId != null) {
                    Set<Integer> l_childrenDirIds = dirMapping.get(parentId);
                    if (l_childrenDirIds == null) {
                        l_childrenDirIds = new LinkedHashSet<Integer>();
                        dirMapping.put(parentId, l_childrenDirIds);
                    }
                    l_childrenDirIds.add(id);
                }

            }
        }
        return cftd;
    }
}
